-
-
Notifications
You must be signed in to change notification settings - Fork 35.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix perturbNormal2Arb() bug #13716
Fix perturbNormal2Arb() bug #13716
Conversation
@donmccurdy Unrelated: Any idea why the model has |
From GLTFLoader.js:1992 — // Normal map textures use OpenGL conventions:
// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#materialnormaltexture
if ( material.normalScale ) {
material.normalScale.x = - material.normalScale.x;
} EDIT: Related to #11315. |
Wohoo! Thanks for making the PR @WestLangley and improving the solution to be more precise. |
@donmccurdy I do not think // Normal map textures use OpenGL conventions:
// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#materialnormaltexture
if ( material.normalScale ) {
material.normalScale.x = - material.normalScale.x;
} A reasonable guess is the model was created for BabylonJS. If a user wants to use the model in three.js, the user should set |
Thanks! |
Uh oh... |
I don't think that's the case, but would be more confident if I knew the answer to #11315. 😅 If the model uses BabylonJS's normal handedness, it is an invalid glTF file. I'll look into this in a bit. |
On closer look, BabylonJS inverts normal map X when using their default left-handed system. |
@donmccurdy After this PR the boombox normalmap seems to have been inverted. That |
I've tested with NormalTangentTest and NormalTangentMirrorTest and, after this PR and with this code they look correct: if ( material.normalScale ) {
material.normalScale.y = - material.normalScale.y;
} 🤔 |
This is all good news, but the loader should not change the model parameters. The correct fix is to properly set |
Agreed. |
The handedness of the three.js normal map system remains unanswered in #11315. If it is not the same as the OpenGL convention (which all glTF assets must use) then inverting an axis of |
Actually, this shouldn't be the problem. Otherwise this would be a bug in the GLTF spec. The model should look identical in any engine. |
I would suggest standardizing on Unity and UE4 style normal map interpretation. I believe they are the same thing. |
I would say the three.js tangent space coordinate convention is positive-x is to the right, and positive-y is up. |
Hilarious, UE4 and Unity have different conventions - in fact the supporters of each of the two formats have equal supporters: http://www.werwackfx.com/index.php/graphictools/graphicsarticles/graphics-articles/45-normalmapsart I think you should then have a parameter to support both, call one OpenGL and the other DirectX, and have documentation that lists the various programs that support these two styles. OpenGL might as well be the default. |
We have a parameter that supports both: |
My recommendation is a public parameter called normalMapStyle. It would be separate from normalMapScale, which technically should be a scalar anyhow. Thus you would have one style parameter and one scale parameter. It can still be converted into a Vec3 when passed to the shader as it is right now, but my suggested parameterization is a more usable API because it matches how developers think about the problem, rather than expecting developers to jump through non-obvious mental hoops in order to figure out ThreeJS - see @donmccurdy comment. Don is smart, but ThreeJS is confusing him here. |
Another option would be to document the issue whenever we figure out exactly what is the right |
Well, I just try to follow other engines, like Unity and UE4, which expose a single scalar. The behavior when normalScale = Vec2(1,1), ThreeJS operates with brighter green being up, which is OpenGL style. I can understand this:
Much easier than this:
And it also prevents people from doing just incorrect things like this:
|
Agreed, I think the only reason it is not a scalar is to accommodate normal maps authored assuming a different tangent-space coordinate convention. material.normalScale.set( 0.5, - 0.5 ); |
Quick patch in #13784 for r92. Do we want to try the |
I suggest retaining the current pattern, as it is flexible. material.normalScale.set( 0.5, - 0.5 ); |
As discussed in #7094